package hell.satan.droidbdf.utils;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;

/**
 * IO 工具类
 * Input/Output utlis
 *
 * @author Cerberus
 */
@SuppressWarnings("unused")
public class IOUtils {
    protected static final String TAG = IOUtils.class.getSimpleName();

    protected static final long SZ_BUFFER = 8 * Constants.SIZE_KB;
    protected static final long IO_ERROR = -1;

    /**
     * 静默关闭可关闭对象
     * Close Closeable quietly
     *
     * @param closeable 待关闭对象
     *                  Object wanna be closed
     * @return 如果关闭成功返回true。 True if close successfully
     */
    public static boolean closeQuietly(@Nullable Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
                return true;
            }
        } catch (Exception ex) {
            // Ignore
        }
        return false;
    }

    /**
     * 将is流复制到os流中
     * Copy stream from is to os
     *
     * @param is 输入流
     *           Input stream
     * @param os 输入流
     *           Output stream
     * @return 复制的总字节数 Total of bytes copied
     * @
     */
    public static long copy(@NonNull InputStream is, @NonNull OutputStream os) {
        byte[] buffer = new byte[(int) SZ_BUFFER];
        long size = 0;
        int count;
        try {
            while ((count = is.read(buffer)) > 0) {
                os.write(buffer, 0, count);
                size += count;
            }
            return size;
        } catch (IOException ex) {
            LogWrapper.w(TAG, ex);
        }
        return IO_ERROR;
    }

    /**
     * 将rd流复制到wt流中
     * Copy stream from rd to wt
     *
     * @param rd 输入流
     *           Input reader
     * @param wt 输入流
     *           Output writer
     * @return 复制的总字符数 Total of characters copied
     * @
     */
    public static long copy(@NonNull Reader rd, @NonNull Writer wt) {
        char[] buffer = new char[(int) SZ_BUFFER];
        long size = 0;
        int count;
        try {
            while ((count = rd.read(buffer)) > 0) {
                wt.write(buffer, 0, count);
                size += count;
            }
            return size;
        } catch (IOException ex) {
            LogWrapper.w(TAG, ex);
        }
        return IO_ERROR;
    }

    /**
     * 将is流复制到wt流中
     * Copy stream from is to wt
     *
     * @param is      输入流
     *                Input stream
     * @param wt      输入流
     *                Output writer
     * @param charset 字符编码名称
     *                Charset name for encoding
     * @return 复制的总字符数 Total of characters copied
     * @
     */
    public static long copy(@NonNull InputStream is, @NonNull Writer wt, @NonNull String charset) {
        InputStreamReader isr;
        try {
            isr = new InputStreamReader(is, charset);
            return copy(isr, wt);
        } catch (UnsupportedEncodingException ex) {
            LogWrapper.w(TAG, ex);
        }
        return IO_ERROR;
    }

    /**
     * 将is流复制到wt流中
     * Copy stream from is to wt
     *
     * @param is 输入流
     *           Input stream
     * @param wt 输入流
     *           Output writer
     * @return 复制的总字符数 Total of characters copied
     * @
     */
    public static long copy(@NonNull InputStream is, @NonNull Writer wt) {
        return copy(is, wt, Constants.CHARSET);
    }

    /**
     * 将rd流复制到os流中
     * Copy stream from is to wt
     *
     * @param rd      输入流
     *                Input stream
     * @param os      输入流
     *                Output writer
     * @param charset 字符编码名称
     *                Charset name for encoding
     * @return 复制的总字符数 Total of characters copied
     * @
     */
    public static long copy(@NonNull Reader rd, @NonNull OutputStream os, @NonNull String charset) {
        OutputStreamWriter osw;
        try {
            osw = new OutputStreamWriter(os, charset);
            return copy(rd, osw);
        } catch (UnsupportedEncodingException ex) {
            LogWrapper.w(TAG, ex);
        }
        return IO_ERROR;
    }

    /**
     * 将rd流复制到os流中
     * Copy stream from is to wt
     *
     * @param rd 输入流
     *           Input stream
     * @param os 输入流
     *           Output writer
     * @return 复制的总字符数 Total of characters copied
     * @
     */
    public static long copy(@NonNull Reader rd, @NonNull OutputStream os) {
        return copy(rd, os, Constants.CHARSET);
    }

    /**
     * 读取流，并转换成字符串
     *
     * @param is      输入流
     *                Input stream
     * @param charset 字符编码名称
     *                Charset name for encoding
     * @return 读取结果 Read result
     */
    public static String read(InputStream is, String charset) {
        StringWriter sr = null;
        try {
            sr = new StringWriter();
            copy(is, sr, charset);
            return sr.toString();
        } finally {
            closeQuietly(sr);
        }
    }

    /**
     * 读取流，并转换成字符串
     *
     * @param is 输入流
     *           Input stream
     * @return 读取结果 Read result
     */
    public static String read(InputStream is) {
        return read(is, Constants.CHARSET);
    }

    /**
     * 读取流，并转换成字符串
     *
     * @param rd 输入流
     *           Input reader
     * @return 读取结果 Read result
     */
    public static String read(Reader rd) {
        StringWriter sr = null;
        try {
            sr = new StringWriter();
            copy(rd, sr);
            return sr.toString();
        } finally {
            closeQuietly(sr);
        }
    }

    /**
     * 将字符串写入流中
     *
     * @param os      输出流
     *                Output stream
     * @param value   待输出字符串值
     *                The string to be output
     * @param charset 字符编码名称
     *                Charset name for encoding
     */
    public static void write(OutputStream os, String value, String charset) {
        StringReader sr = null;
        try {
            sr = new StringReader(value);
            copy(sr, os, charset);
        } finally {
            closeQuietly(sr);
        }
    }

    /**
     * 将字符串写入流中
     *
     * @param os    输出流
     *              Output stream
     * @param value 待输出字符串值
     *              The string to be output
     */
    public static void write(OutputStream os, String value) {
        write(os, value, Constants.CHARSET);
    }

    /**
     * 将字符串写入流中
     *
     * @param wt    输出流
     *              Output stream
     * @param value 待输出字符串值
     *              The string to be output
     */
    public static void write(Writer wt, String value) {
        StringReader sr = null;
        try {
            sr = new StringReader(value);
            copy(sr, wt);
        } finally {
            closeQuietly(sr);
        }
    }
}
